package cn.py.boot_lua.util;

import ch.qos.logback.classic.Logger;
import org.apache.commons.io.IOUtils;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.entity.UrlEncodedFormEntity;
import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.NameValuePair;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.io.entity.StringEntity;
import org.apache.hc.core5.http.message.BasicNameValuePair;
import org.apache.hc.core5.util.Timeout;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.*;


@Component
public class HttpUtils {
    private static final Logger logger = (Logger) LoggerFactory.getLogger(HttpUtils.class);
    private static PoolingHttpClientConnectionManager connMgr = new PoolingHttpClientConnectionManager();
    private static RequestConfig requestConfig;

    public HttpUtils() {
    }

    /**
     * post,以 application/json 形式
     * @param apiUrl
     * @param json
     * @return
     */
    public static String doPost(String apiUrl, String json) {
        long start = System.currentTimeMillis();
        CloseableHttpClient httpClient = HttpClients.createDefault();
        String httpStr = null;
        HttpPost httpPost = new HttpPost(apiUrl);
        CloseableHttpResponse response = null;
        int statusCode = -999;
        try {
            httpPost.setConfig(requestConfig);
            StringEntity stringEntity = new StringEntity(json, ContentType.APPLICATION_JSON,"UTF-8", false);
            httpPost.setEntity(stringEntity);
            response = httpClient.execute(httpPost);
            HttpEntity entity = response.getEntity();
            statusCode = response.getCode();
            httpStr = EntityUtils.toString(entity, "UTF-8");
        } catch (Exception var20) {
            logger.info("HttpUtil post error:" + var20.getMessage());
            var20.printStackTrace();
        } finally {
            if (response != null) {
                try {
                    EntityUtils.consume(response.getEntity());
                } catch (IOException var19) {
                    var19.printStackTrace();
                }
            }

            logger.info("request to:{},param:{},response code:{},result:{},cost {} ms", new Object[]{apiUrl, json, statusCode, httpStr, System.currentTimeMillis() - start});
        }

        return httpStr;
    }

    /**
     * Post方式
     * @param apiUrl
     * @param json json数据
     * @param headerMap 请求头
     * @return
     */
    public static String doPost(String apiUrl, String json, Map<String,String> headerMap) {
        long start = System.currentTimeMillis();
        CloseableHttpClient httpClient = HttpClients.createDefault();
        String httpStr = null;
        HttpPost httpPost = new HttpPost(apiUrl);
        CloseableHttpResponse response = null;
        int statusCode = -999;

        try {
            httpPost.setConfig(requestConfig);
            StringEntity stringEntity = new StringEntity(json, ContentType.APPLICATION_JSON,"UTF-8", false);
            //循环增加header
            if (headerMap != null) {
                for (Map.Entry<String, String> entry : headerMap.entrySet()) {
                    httpPost.addHeader(entry.getKey(), entry.getValue());
                }
            }
            httpPost.setEntity(stringEntity);
            response = httpClient.execute(httpPost);
            HttpEntity entity = response.getEntity();
            statusCode = response.getCode();
            httpStr = EntityUtils.toString(entity, "UTF-8");
        } catch (Exception var20) {
            logger.info("HttpUtil post error:" + var20.getMessage());
            var20.printStackTrace();
        } finally {
            if (response != null) {
                try {
                    EntityUtils.consume(response.getEntity());
                } catch (IOException var19) {
                    var19.printStackTrace();
                }
            }

            logger.info("request to:{},param:{},response code:{},result:{},cost {} ms", new Object[]{apiUrl, json, statusCode, httpStr, System.currentTimeMillis() - start});
        }

        return httpStr;
    }

    /**
     * Post请求
     * @param apiUrl 请求链接
     * @param params 请求类型：x-www-form-urlencoded
     * @return
     */
    public static String doPost(String apiUrl, Map<String, Object> params) {
        long start = System.currentTimeMillis();
        CloseableHttpResponse response = null;
        String httpStr = null;
        int statusCode = -999;
        //创建http实例
        CloseableHttpClient httpClient = HttpClients.createDefault();
        //创建httpPost实例
        HttpPost httpPost = new HttpPost(apiUrl);
        try {
            httpPost.setConfig(requestConfig);
            List<NameValuePair> pairList = new ArrayList<>();
//            遍历参数
            for (Map.Entry<String, Object> entry : params.entrySet()) {
                NameValuePair pair = new BasicNameValuePair(entry.getKey(), entry.getValue().toString());
                pairList.add(pair);
            }
            httpPost.setEntity(new UrlEncodedFormEntity(pairList, StandardCharsets.UTF_8));
            response = httpClient.execute(httpPost);
            statusCode = response.getCode();
            HttpEntity entity = response.getEntity();
            httpStr = EntityUtils.toString(entity, "UTF-8");
        } catch (Exception e) {
            logger.info("HttpUtil发生错误:" + e.getMessage());
            e.printStackTrace();
        } finally {
            if (response != null) {
                try {
                    EntityUtils.consume(response.getEntity());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            logger.info("request path:{}, param:{},response code:{},result:{},cost {} ms", new Object[]{apiUrl, params.toString(), statusCode, httpStr, System.currentTimeMillis() - start});
        }

        return httpStr;
    }


    /**
     * @param url url链接
     * @param headMaps 请求头参数
     * @param params 请求体参数
     * @param multipartFile 上传文件,可上传单文件或者多文件
     * @return
     */
    public static String sendMultipartFilePost(String url, Map<String,String> headMaps,
                                               Map<String, Object> params,
                                               Map<String, File> multipartFile) {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        String result = null;
        try {
            HttpPost httpPost = new HttpPost(url);
            if(headMaps!=null){
                //循环增加header
                for (Map.Entry<String, String> entry : headMaps.entrySet()) {
                    httpPost.addHeader(entry.getKey(), entry.getValue());
                }
            }
            //文件上传
            MultipartEntityBuilder builder = MultipartEntityBuilder.create();
            builder.setCharset(StandardCharsets.UTF_8);
            //解决中文乱码
//            ContentType contentType = ContentType.create("UTF-8");
            for (Map.Entry<String, Object> entry : params.entrySet()) {
                if(entry.getValue() == null) {
                    continue;
                }
                //类似浏览器表单提交
                builder.addTextBody(entry.getKey(), entry.getValue().toString(), ContentType.TEXT_PLAIN.withCharset("UTF-8"));
            }
            if(multipartFile != null){
                for (Map.Entry<String, File> entry: multipartFile.entrySet()){
                    if(entry.getValue() == null) {
                        continue;
                    }
                    builder.addBinaryBody(entry.getKey(), entry.getValue());
                }
            }
            HttpEntity entity = builder.build();
            httpPost.setEntity(entity);
            //执行提交
            CloseableHttpResponse response = httpClient.execute(httpPost);
            HttpEntity responseEntity = response.getEntity();
            if (responseEntity != null) {
                //将响应内容转换为字符串
                result = EntityUtils.toString(responseEntity, StandardCharsets.UTF_8);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            logger.info("request to:{},param:{},file:{}", new Object[]{url,params.toString()});
        }
        return result;
    }


    /**
     * @param url
     * @param params 带参数
     * @return
     */
    public static String doGet(String url, Map<String, Object> params,String path) throws IOException {
        long start = System.currentTimeMillis();
        StringBuilder param = new StringBuilder();
        int i = 0;
        for(Iterator<String> i$ = params.keySet().iterator(); i$.hasNext(); ++i) {
            String key = i$.next();
            if (i == 0) {
                param.append("?");
            } else {
                param.append("&");
            }
            if (key.equals("text") ||key.equals("name")) {
                String value = URLEncoder.encode(params.get(key).toString(), StandardCharsets.UTF_8);
                param.append(key).append("=").append(value);
                continue;
            }

            param.append(key).append("=").append(params.get(key));

        }
        String apiUrl = url + param;
        String result = null;
        //创建一个httpClient
        CloseableHttpClient httpClient = HttpClients.createDefault();
        int statusCode = -999;
        try {
            HttpGet httpGet = new HttpGet(apiUrl);
            CloseableHttpResponse response = httpClient.execute(httpGet);
            statusCode = response.getCode();
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                InputStream instream = entity.getContent();
                Files.copy(instream, Paths.get(path), StandardCopyOption.REPLACE_EXISTING);
                result = path;
            }
        } catch (Exception var18) {
            logger.info("httputil get error:" + var18.getMessage());
            var18.printStackTrace();
        } finally {
            if (httpClient != null) {
                httpClient.close();
            }
            logger.info("request to:{},param:{},response code:{},result:{},cost {} ms", new Object[]{apiUrl, param.toString(), statusCode, result, System.currentTimeMillis() - start});
        }

        return result;
    }

    /**
     * 请求方式 Get
     * @param url 请求链接
     * @param params 以 x-www-form-urlencoded
     * @param headerMap 请求头参数
     * @return
     */
    public static String doGet(String url, Map<String, Object> params, Map<String,String> headerMap) throws IOException {
        long start = System.currentTimeMillis();
        StringBuffer param = new StringBuffer();
        int i = 0;

        for(Iterator i$ = params.keySet().iterator(); i$.hasNext(); ++i) {
            String key = (String)i$.next();
            if (i == 0) {
                param.append("?");
            } else {
                param.append("&");
            }

            param.append(key).append("=").append(params.get(key));
        }

        String apiUrl = url + param;
        String result = null;
        CloseableHttpClient httpClient = HttpClients.createDefault();
        int statusCode = -999;

        try {
            HttpGet httpGet = new HttpGet(apiUrl);
            //循环增加header
            if (headerMap != null) {
                for (Map.Entry<String, String> entry : headerMap.entrySet()) {
                    httpGet.addHeader(entry.getKey(), entry.getValue());
                }
            }
            CloseableHttpResponse response = httpClient.execute(httpGet);
            statusCode = response.getCode();
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                InputStream instream = entity.getContent();
                result = IOUtils.toString(instream, "UTF-8");
            }
        } catch (Exception e) {
            logger.info("HttpUtil发生错误:" + e.getMessage());
            e.printStackTrace();
        } finally {
            if (httpClient != null) {
                httpClient.close();
            }
        }
        return result;
    }

    static {
        connMgr.setMaxTotal(100);
        connMgr.setDefaultMaxPerRoute(connMgr.getMaxTotal());
        RequestConfig.Builder configBuilder = RequestConfig.custom();
        configBuilder.setConnectTimeout(Timeout.ofMilliseconds(600000));
        configBuilder.setResponseTimeout(Timeout.ofMilliseconds(600000));
        configBuilder.setConnectionRequestTimeout(Timeout.ofMilliseconds(600000));
        requestConfig = configBuilder.build();
    }


}

